﻿package com.singlenotion.display.lists
{
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	import gs.TweenLite;
	
	/**
	 * 
	 * @author Adam Jowett (Single Notion)
	 */
	public class ScrollingList extends MovieClip
	{
		protected var _items:Array;
		protected var _listHeight:Number;
		protected var _listWidth:Number;
		protected var _fontName:String;
		protected var _fontSize:Number;
		protected var _fontColour:int;
		protected var _fontOverColour:int;
		protected var _caps:Boolean;
		protected var _listHolder:Sprite;
		protected var _selectedItem:Object;
		protected var _inventory:Array;
		private var _listMask:Sprite;
		
		/**
		 * A class to dynamically create a scrolling vertical list
		 * 
		 * @author 	Adam Jowett (Single Notion)
		 * 
		 * @param	$items - an array of objects, each object much contain a title parameter, e.g. [{title:"test", id:1}].
		 * @param	$width - the width of the list, this is used by the mask.
		 * @param	$height - the height of the list, this is used by the mask.
		 * @param	$fontName - the name of the font which is already embedded where the list is to be placed.
		 * @param	$fontSize - the size of the embedded font.
		 * @param	$fontColour - the colour of the font.
		 * @param	$caps - whether each item should be automatically all in caps.
		 */
		public function ScrollingList(	$items:Array, $width:Number, $height:Number, $fontName:String, $fontSize:Number = 12, 
										$fontColour:int = 0xFFFFFF, $fontOverColour:int = 0x00CC33, $caps:Boolean = false) 
		{
			_items = $items;
			_listHeight = $height;
			_listWidth = $width;
			_fontName = $fontName;
			_fontSize = $fontSize;
			_fontColour = $fontColour;
			_fontOverColour = $fontOverColour;
			_caps = $caps;
			
			addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
			addEventListener(Event.REMOVED_FROM_STAGE, destroy, false, 0, true);
		}
		
		/**********************************************************************************/
				
		protected function init($e:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			addEventListener(Event.ENTER_FRAME, scrollList, false, 0, true);
			
			build(_items);
		}
		
		public function destroy($e:Event):void
		{
			removeEventListener(Event.ENTER_FRAME, scrollList);
			removeEventListener(Event.REMOVED_FROM_STAGE, destroy);
		}
		
		/***********************************************************************************/
		
		protected function build($items:Array):void
		{
			_inventory = new Array();
			
			_listHolder = new Sprite();
			addChild(_listHolder);
			
			var i:int;
			var l:int = $items.length;
			
			for (i = 0; i < l; i++) {
				
				var item:Object = $items[i];
				
				var itemHolder:Sprite = new Sprite();
				itemHolder.buttonMode = true;
				itemHolder.mouseChildren = false;
				
				itemHolder.addEventListener(MouseEvent.MOUSE_DOWN, itemPressListener, false, 0, true);
				itemHolder.addEventListener(MouseEvent.CLICK, itemReleaseListener, false, 0, true);
				itemHolder.addEventListener(MouseEvent.MOUSE_OVER, itemRollOverListener, false, 0, true);
				itemHolder.addEventListener(MouseEvent.MOUSE_OUT, itemRollOutListener, false, 0, true);
				
				var listItem:TextField = new TextField();
				listItem.embedFonts = true;
				listItem.autoSize = TextFieldAutoSize.LEFT;
				listItem.selectable = false;
				listItem.htmlText = (_caps == true) ? String(item.title).toUpperCase() : item.title;
				
				var listFormat:TextFormat = new TextFormat();
				listFormat.font = _fontName;
				listFormat.size = _fontSize;
				listFormat.color = _fontColour;
				
				listItem.setTextFormat(listFormat);
				
				itemHolder.addChild(listItem);
				
				itemHolder.x = 0;
				itemHolder.y = _listHolder.height;
				
				_listHolder.addChild(itemHolder);
				
				_inventory.push(itemHolder);
			}
			
			addMask();
		}
		
		protected function addMask():void
		{
			_listMask = new Sprite();
			_listMask.graphics.clear();
			_listMask.graphics.beginFill(0x990000, 0.5);
			_listMask.graphics.drawRect(0, 0, _listWidth, _listHeight);
			addChild(_listMask);
			
			mask = _listMask;
		}
		
		protected function itemPressListener($e:MouseEvent):void 
		{
			
		}
		
		protected function itemReleaseListener($e:MouseEvent):void 
		{
			// return the previously selected item back to it's up state
			if (_selectedItem != null) TweenLite.to(_selectedItem, 0.3, { removeTint:true } );
			
			_selectedItem = $e.target;
			
			dispatchEvent(new Event(ScrollingListEvents.ITEM_SELECTED, true, true));
		}
		
		protected function itemRollOverListener($e:MouseEvent):void 
		{
			TweenLite.to($e.target, 0.3, { tint:_fontOverColour } );
		}
		
		protected function itemRollOutListener($e:MouseEvent):void 
		{
			if ($e.target != _selectedItem) TweenLite.to($e.target, 0.3, { removeTint:true } );
		}
		
		protected function scrollList($e:Event):void 
		{
			if (_listHolder.height > _listMask.height) {
				
				var scrollMask:Sprite = _listMask;
				var scrollMC:Sprite = _listHolder;
				var buffer:Number = 5;
				
				var tweenTime:Number = 1;
				var speed:Number = 0.5;
				
				if (hitTestPoint(root.mouseX, root.mouseY, false)) {
					
					var centerY:Number = scrollMask.y + scrollMask.height / 2;
					
					var distY:Number = mouseY - centerY;
					
					var newY:Number = scrollMC.y - (distY * speed);
					
					if (newY > scrollMask.y + buffer) newY = scrollMask.y + buffer;
					if (newY < -scrollMC.height - buffer + scrollMask.height + scrollMask.y) newY = -scrollMC.height - buffer + scrollMask.height + scrollMask.y;
					
					TweenLite.to(scrollMC, tweenTime, { y:newY } );
				}
			}
		}
		
		/**
		 * Method to manually highlight an item in the list
		 * @param	$index - the zero based index of the item to be highlighted, e.g. highlightItem(1), to highlight the second item in the list
		 */
		public function highlightItem($index:int):void
		{
			var i:int;
			var l:int = _inventory.length;
			for (i = 0; i < l; i++) 
			{
				var item:Sprite = _inventory[i];
				if (i == $index) 
				{	
					var diff:Number = (item.y - _listMask.height); // (item.y + _listHolder.y) - _listMask.height + item.height;
					if (item.y - diff <= _listMask.height) TweenLite.to(_listHolder, 0.6, { y:-item.y } );
					
					TweenLite.to(item, 0.3, { tint:0xFFFFFF } );
					item.buttonMode = false;
					
				} else {
					TweenLite.to(item, 0.3, { removeTint:true } );
					item.buttonMode = true;
				}
			}
			
			_selectedItem = _inventory[$index];
		}
		
		public function get selectedItem():Object 
		{ 
			return _items[_inventory.indexOf(_selectedItem)];
		}
	}
	
}